// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package time

import "errors"

// 一个自动售票机有一个频道，它每隔一段时间发送一个时钟的“滴答声”。
type Ticker struct {
	C <-chan Time // 发送滴答声的频道。
	r runtimeTimer
}

// NewTicker返回一个新的报价器，其中包含一个频道，该频道将在每个滴答声后发送
// 频道上的当前时间。
// 滴答声的周期由duration参数指定。自动售票机将调整
// 时间间隔或减少滴答声，以弥补接收速度慢的问题。
// 持续时间d必须大于零；如果没有，纽蒂克会惊慌失措。停止股票代码以释放相关资源。
func NewTicker(d Duration) *Ticker {
	if d <= 0 {
		panic(errors.New("non-positive interval for NewTicker"))
	}
	// 为通道提供一个1元素的时间缓冲区。
	// 如果客户在阅读时落后，我们会把滴答声
	// 扔在地板上，直到客户赶上。
	c := make(chan Time, 1)
	t := &Ticker{
		C: c,
		r: runtimeTimer{
			when:   when(d),
			period: int64(d),
			f:      sendTime,
			arg:    c,
		},
	}
	startTimer(&t.r)
	return t
}

// Stop关闭股票行情。停止后，将不再发送滴答声。
// 停止不会关闭通道，以防止并发的goroutine 
// 从通道读取时看到错误的“滴答声”。
func (t *Ticker) Stop() {
	stopTimer(&t.r)
}

// Reset停止一个股票代码，并将其周期重置为指定的持续时间。
// 下一个滴答声将在新时段过后到达。持续时间d 
// 必须大于零；如果没有，重置将导致死机。
func (t *Ticker) Reset(d Duration) {
	if d <= 0 {
		panic("non-positive interval for Ticker.Reset")
	}
	if t.r.f == nil {
		panic("time: Reset called on uninitialized Ticker")
	}
	modTimer(&t.r, when(d), int64(d), t.r.f, t.r.arg, t.r.seq)
}

// Tick是NewTicker的便利包装，只提供对滴答声
// 频道的访问。虽然Tick对那些不需要关闭
// /行情器的客户很有用，但请注意，如果无法关闭它，垃圾收集器将无法恢复底层
// /行情器；它“泄露”。
// 与NewTicker不同，如果d<=0，则Tick将返回nil。
func Tick(d Duration) <-chan Time {
	if d <= 0 {
		return nil
	}
	return NewTicker(d).C
}
